package cuatroenraya.jugadores;

import javax.swing.JOptionPane;
import cuatroenraya.gui.JugadorGUIHandler;
import cuatroenraya.Jugador;
import cuatroenraya.Arbitro;

public class Genetica {
	
	public Genetica(){} // Constructor
	
	
	public void torneoFinal(int numeroSetsPorPartido){
	// Método utilizada para hacer competir los ganadores precedentes
		
		int numeroJugadoresPorLista=4;
		JugadorAlumnoG9 ganador;
		
		JugadorAlumnoG9[] listaIzquierda=new JugadorAlumnoG9[numeroJugadoresPorLista];
		JugadorAlumnoG9[] listaDerecha=new JugadorAlumnoG9[numeroJugadoresPorLista];
		
		listaIzquierda[0]=new JugadorAlumnoG9(14,72,35,43,22);
		listaIzquierda[1]=new JugadorAlumnoG9(2,96,89,91,31);
		listaIzquierda[2]=new JugadorAlumnoG9(2,66,30,6,68);
		listaIzquierda[3]=new JugadorAlumnoG9(6,58,32,41,41);
		
		listaDerecha[0]=new JugadorAlumnoG9(21,74,57,53,70);
		listaDerecha[1]=new JugadorAlumnoG9(13,75,43,64,51);
		listaDerecha[2]=new JugadorAlumnoG9(8,96,96,62,21);
		listaDerecha[3]=new JugadorAlumnoG9(13,78,13,50,21);
		
		ganador = torneoRec(listaIzquierda, listaDerecha, numeroJugadoresPorLista, 
												numeroSetsPorPartido);
		System.out.println(" El ultimo ganador es :");
		ganador.printParamJugador("ganador");
		
	}// Fin del método torneoFinal
	
	
	public void torneo(int numeroDeNiveles, int numeroSetsPorPartido){
		// Crea dos listas jugadores de jugadores con parametros aleatorios, 
		// y llama torneoRec con estos listas. 
		// llamar con numeroDeNiveles >2
		
		// el numero de jugadors iniciales es 2^numeroDeNiveles
		int numeroJugadoresPorLista=(int)Math.pow(2,(double)(numeroDeNiveles-1));
		
		// creacion de las listas
		JugadorAlumnoG9[] listaIzquierda=new JugadorAlumnoG9[numeroJugadoresPorLista];
		JugadorAlumnoG9[] listaDerecha=new JugadorAlumnoG9[numeroJugadoresPorLista];
		int indiceLista;
		JugadorAlumnoG9 ganador;
		
		for (indiceLista=0;indiceLista<numeroJugadoresPorLista;indiceLista++){
			listaIzquierda[indiceLista]=new JugadorAlumnoG9(
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100));
		}
		for (indiceLista=0;indiceLista<numeroJugadoresPorLista;indiceLista++){
			listaDerecha[indiceLista]= new JugadorAlumnoG9(
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100),
							(int)Math.floor(Math.random()*100));
		}
		ganador = torneoRec(listaIzquierda, listaDerecha, 
									numeroJugadoresPorLista,numeroSetsPorPartido);
		System.out.println(" El ultimo ganador es :");
		ganador.printParamJugador("ganador");
		
	}// Fin del método torneo
	
	private JugadorAlumnoG9 torneoRec(JugadorAlumnoG9[] listaIzquierda,
									JugadorAlumnoG9[] listaDerecha,
									int numeroJugadoresPorLista,
									int numeroDeSets){
		// Método recursivo que simula un torneo entre 
		// los jugadores de los listas parametras.
		// Algotritmo inspirado de Mergesort (arból inversado)
		// Llama al método partido.
		
		JugadorAlumnoG9 ganador;
		int indiceLista;
		int nuevoNumJugPorLista;
		
		// Si queda solo un jugador por lista :
		// Partido final del torneo
		if (numeroJugadoresPorLista==1){
			return partido(listaIzquierda[0], listaDerecha[0], numeroDeSets);
		}
		
		// Cortamos las listas en dos
		nuevoNumJugPorLista=numeroJugadoresPorLista/2;
		JugadorAlumnoG9[] listaIzquierdaIzquierda=new JugadorAlumnoG9[nuevoNumJugPorLista];
		JugadorAlumnoG9[] listaIzquierdaDerecha=new JugadorAlumnoG9[nuevoNumJugPorLista];
		JugadorAlumnoG9[] listaDerechaIzquierda=new JugadorAlumnoG9[nuevoNumJugPorLista];
		JugadorAlumnoG9[] listaDerechaDerecha=new JugadorAlumnoG9[nuevoNumJugPorLista];
		
			for (indiceLista=0;indiceLista<nuevoNumJugPorLista;indiceLista++){
				listaIzquierdaIzquierda[indiceLista]=listaIzquierda[indiceLista];
			}
			for (indiceLista=0;indiceLista<nuevoNumJugPorLista;indiceLista++){
				listaIzquierdaDerecha[indiceLista]=
								listaIzquierda[indiceLista+numeroJugadoresPorLista/2];
			}
			for (indiceLista=0;indiceLista<nuevoNumJugPorLista;indiceLista++){
				listaDerechaIzquierda[indiceLista]=listaDerecha[indiceLista];
			}
			for (indiceLista=0;indiceLista<nuevoNumJugPorLista;indiceLista++){
				listaDerechaDerecha[indiceLista]=
								listaDerecha[indiceLista+numeroJugadoresPorLista/2];
			}
			
		// Organizamos un partido entre los ganadores de torneoRec, 
		// pasando las nuevas listas		
		ganador=partido(torneoRec(listaIzquierdaIzquierda, listaIzquierdaDerecha, 
											nuevoNumJugPorLista, numeroDeSets),
						torneoRec(listaDerechaIzquierda,listaDerechaDerecha, 
								nuevoNumJugPorLista,numeroDeSets),numeroDeSets);
		
		return ganador;
	}// Fin del método torneoRec
	
	
	public JugadorAlumnoG9 partido(
						JugadorAlumnoG9 jugA, JugadorAlumnoG9 jugB, int numeroDeSets){
		// un partido esta componiendo por numeroDeSets Sets
		// Al fin de cada set, calculamos los parametros del jugador hijo 
		// segun quien del padre o de la madre gano
		int setCounter;
		int parametrosDelHijo[] = new int[5];
		int parametrosDeLosPadres[][] = new int [3][5];
		int numeroEmpates=0;
		int numeroSetsSinEmpates;
		int resultadoDelSet;
		
		parametrosDeLosPadres[0]=(new int[]{0,0,0,0,0});
		parametrosDeLosPadres[1]=jugA.GetParametrosDelJugador();
		parametrosDeLosPadres[2]=jugB.GetParametrosDelJugador();
		
		for (setCounter=0; setCounter<numeroDeSets; setCounter++){
			resultadoDelSet=set(jugA,jugB);
			// 0 si empate, 1 si gana jugA, 2 si gana jugB
			
			parametrosDelHijo[0]+=parametrosDeLosPadres[resultadoDelSet][0];
			parametrosDelHijo[1]+=parametrosDeLosPadres[resultadoDelSet][1];
			parametrosDelHijo[2]+=parametrosDeLosPadres[resultadoDelSet][2];
			parametrosDelHijo[3]+=parametrosDeLosPadres[resultadoDelSet][3];
			parametrosDelHijo[4]+=parametrosDeLosPadres[resultadoDelSet][4];

			numeroEmpates+=((2-resultadoDelSet)/2);
			
		}
		
		numeroSetsSinEmpates=numeroDeSets-numeroEmpates;
		
		if (numeroSetsSinEmpates==0){ // hubo solo empates => 
		//el hijo esta 50% del padre, y 50% de la madre
			JugadorAlumnoG9 hijo = new JugadorAlumnoG9(
					(parametrosDeLosPadres[1][0]+parametrosDeLosPadres[2][0])/2,
					(parametrosDeLosPadres[1][1]+parametrosDeLosPadres[2][1])/2,
					(parametrosDeLosPadres[1][2]+parametrosDeLosPadres[2][2])/2,
					(parametrosDeLosPadres[1][3]+parametrosDeLosPadres[2][3])/2,
					(parametrosDeLosPadres[1][4]+parametrosDeLosPadres[2][4])/2);
			return hijo;
		}
		// los parametros de hijo son los parametros de los padres 
		//ponderados por el numero de victorias de cada uno
		JugadorAlumnoG9 hijo = new JugadorAlumnoG9(
								parametrosDelHijo[0]/numeroSetsSinEmpates,
								parametrosDelHijo[1]/numeroSetsSinEmpates,
								parametrosDelHijo[2]/numeroSetsSinEmpates,
								parametrosDelHijo[3]/numeroSetsSinEmpates,
								parametrosDelHijo[4]/numeroSetsSinEmpates);
		
		jugA.printParamJugador("madre (1)");
		jugB.printParamJugador("padre (2)");
		hijo.printParamJugador("hijo");
		
		return hijo;
    }// Fin del método partido
	

	public int set(Jugador jugA, Jugador jugB){
		// inspirado por el Main del profesor 

        // Crear el Arbitro.
        Arbitro arb = new Arbitro();

        // Empezar los partidos.
        int resultado = arb.EmpezarPartido(jugA, jugB, null);
        return resultado;
    }//Fin del método set

}// Fin de la classe Genetica
